import * as THREE from "three";
import { MathUtils } from 'three';
import { threeViewStore } from "../../store/models/data";
var moveFlag = false;//用来判断鼠标是否发生和拖拽旋转模型的动作，用以和鼠标点击事件做区分
let pointArrVector3: Array<THREE.Vector3> = [];//用来存储v3格式点坐标
let pointArrObj: Array<THREE.Object3D> = [];//用来存储定义后的points对象
let lineArrObj: Array<THREE.Object3D> = [];//用来存储定义后的Line对象
let labelText = document.createElement('span');
const store = threeViewStore();
export default function angle(angleVis: any) {
    // 绘制三个点，根据这三个点连两条线，然后测量两条线对应的两个向量的夹角
    let domContainer = document.getElementById("threeContainer");
    if (angleVis) {
        // 绘制两个点连接一条线，再根据mousemove获取到与射线相交的第三个点，动态绘制线，并动态计算角度
        domContainer.style.cursor = "crosshair";
        domContainer?.addEventListener("mousedown", onmousedown);
        window.controls.addEventListener("change", onPointerMove);
        domContainer?.addEventListener("mouseup", onPointerClick);
    }
    else {
        domContainer.style.cursor = "default";
        domContainer?.removeEventListener("mouseup", onPointerClick);
        domContainer?.removeEventListener("mousedown", onmousedown);
        window.controls.removeEventListener("change", onPointerMove);
        domContainer?.removeEventListener("mousemove", onMousemove);
    }
}
/**鼠标按下点击事件 */
function onmousedown() {
    moveFlag = false;//如果鼠标发生了移动，就将moveFlag设置为false,则不再触发onPointerClick方法，即不再绘制点
}
/**鼠标change事件,用来判断区分是模型旋转还是鼠标点击 */
function onPointerMove() {
    moveFlag = true;
}

/**鼠标抬起点击事件 */
function onPointerClick(event: any) {
    let domContainer = document.getElementById("threeContainer");
    if (!moveFlag) {
        console.log(pointArrVector3, 'pointArrVector3---');
        if (pointArrVector3.length === 0) {
            let position = getPositionVector3(event);
            // 如果绘制的是第一个点就绘制点
            drawPoint(position);
        }
        else if (pointArrVector3.length === 1) {
            // 如果绘制的是第二个点就绘制点和线
            let position = getPositionVector3(event);
            drawPoint(position);
            drawLine(pointArrVector3[0], pointArrVector3[1]);
            domContainer?.addEventListener("mousemove", onMousemove);
        }
        else if (pointArrVector3.length === 2) {
            let position = getPositionVector3(event);
            drawPoint(position);
            domContainer?.removeEventListener("mousemove", onMousemove);
            store.saveAngleData(pointArrObj, lineArrObj, pointArrVector3);
            let angle = getAngle();
            console.log(labelText,'labelText');
              setLabel(angle,event);    
        }
        else {
            // 如果绘制点的个数超过三个，就卸载之前绘制的点线和label
            pointArrObj.forEach((item) => {
                window.threeScene.remove(item);
            })
            lineArrObj.forEach((item) => {
                window.threeScene.remove(item);
            })
            pointArrObj = [];
            lineArrObj = [];
            pointArrVector3 = [];
            labelText.innerHTML = '';
            onPointerClick(event);
        }
    }
}
/**鼠标移动捕获点坐标 */
function onMousemove(event: any) {
    console.log('onMousemove我触发了');
    const pointer = new THREE.Vector2();
    pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
    pointer.y = -(event.clientY / window.innerHeight) * 2 + 1;
    const raycaster = new THREE.Raycaster();
    raycaster.setFromCamera(pointer, window.camera);
    const intersects = raycaster.intersectObjects(window.threeScene.children, true);
    // drawLine(pointArrVector3[1], pointArrVector3[2]);
    if (intersects.length > 0) {
        const vposition = intersects[0].point;
        // 使用vposition作为 第三个点坐标，绘制三条边
        // console.log(vposition, '移动拾取');
        // 绘制第三条边，如果已经绘制过了就修改第三条边
        if (lineArrObj.length === 2) {
            let points = [];
            points.push(...pointArrVector3[1]);
            points.push(...vposition);
            console.log(points, 'points');
            lineArrObj[1].geometry.attributes.position = new THREE.Float32BufferAttribute(points, 3);
            // lineArrObj[1].geometry.setFromPoints(points)
        }
        else {
            console.log(pointArrVector3[1], vposition, 'else----');
            drawLine(pointArrVector3[1], vposition);
        }
    }
}
/**根据event进行屏幕坐标转三维坐标获取点击点位信息 */
function getPositionVector3(event: any) {
    const pointer = new THREE.Vector2();
    pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
    pointer.y = -(event.clientY / window.innerHeight) * 2 + 1;
    const raycaster = new THREE.Raycaster();
    raycaster.setFromCamera(pointer, window.camera);
    let position = [];
    const intersects = raycaster.intersectObjects(window.threeScene.children, true);
    if (intersects.length > 0) {
        let index = 0;
        let x = intersects[index].point.x;
        let y = intersects[index].point.y;
        let z = intersects[index].point.z;
        position.push(x);
        position.push(y);
        position.push(z);
        let vposition = intersects[0].point;
        pointArrVector3.push(vposition);
        console.log(pointArrVector3, 'pointArrVector3');

        return position;
    }
}
/**绘制点 */
function drawPoint(position: any) {
    const geometry = new THREE.BufferGeometry();
    const color = new Float32Array([1, 0, 0]);
    geometry.setAttribute('position', new THREE.Float32BufferAttribute(position, 3));
    geometry.setAttribute('color', new THREE.BufferAttribute(color, 3));
    geometry.computeBoundingSphere();
    // 定义材质
    // 如果需要绘制点线可以被模型遮挡，把depthTest设置为true即可
    const material = new THREE.PointsMaterial({ size: 0.1, vertexColors: true, depthTest: false });
    const drawpoint = new THREE.Points(geometry, material);
    pointArrObj.push(drawpoint);
    window.threeScene.add(drawpoint);
}
/**绘制线 */
function drawLine(pointa: THREE.Vector3, pointb: THREE.Vector3) {
    console.log(pointa, pointb, 'pointapointb');
    const geometry = new THREE.BufferGeometry();
    const color = new Float32Array([1, 0, 0]);
    let points = [];
    points.push(...pointa);
    points.push(...pointb);
    geometry.setAttribute('position', new THREE.Float32BufferAttribute(points, 3));
    geometry.setAttribute('color', new THREE.BufferAttribute(color, 3));
    geometry.computeBoundingSphere();
    const material = new THREE.LineBasicMaterial({ vertexColors: false, depthTest: false });
    const line = new THREE.Line(geometry, material);
    console.log(line, 'line');

    line.frustumCulled = false;//这行代码很关键,让屏幕外区域的点,正确显示
    window.threeScene.add(line);
    lineArrObj.push(line);
}
function getAngle() {//v1: THREE.Vector3, v2: THREE.Vector3
    // 两向量夹角在0~180之间。两向量方向相反。夹角为180.两向量方向相同，夹角为0
    let v1v0 = new THREE.Vector3();
    let x_v1v0 = pointArrVector3[1].x - pointArrVector3[0].x;
    let y_v1v0 = pointArrVector3[1].y - pointArrVector3[0].y;
    let z_v1v0 = pointArrVector3[1].z - pointArrVector3[0].z;
    v1v0.x = x_v1v0;
    v1v0.y = y_v1v0;
    v1v0.z = z_v1v0;

    let v1v2 = new THREE.Vector3();
    let x_v1v2 = pointArrVector3[1].x - pointArrVector3[2].x;
    let y_v1v2 = pointArrVector3[1].y - pointArrVector3[2].y;
    let z_v1v2 = pointArrVector3[1].z - pointArrVector3[2].z;
    v1v2.x = x_v1v2;
    v1v2.y = y_v1v2;
    v1v2.z = z_v1v2;
    let angle_hudu = v1v0.angleTo(v1v2);//获取的结果为弧度制，还需要转为角度制
    // console.log(angle_hudu,'angle_hudu');
    let angle = MathUtils.radToDeg(angle_hudu);
    console.log(angle, 'angle');
    return angle;
}

/**创建显示角度的标签 */
function setLabel(angle: Number,event:any) {
    console.log(angle, 'angle--');
    // 后面希望使用css2Drenderer形式实现，暂时使用老方法实现
    labelText.style.position = 'absolute';
    labelText.style.top = '0';
    labelText.style.color = 'red';
    labelText.style.pointerEvents = 'none';
    document.body.appendChild(labelText);
    // 源代码是构建虚线的时候才实时渲染
    pointArrObj[1].onBeforeRender = function () {
        // 设置标签位置，实时渲染
        setLabelPosition(angle,labelText, event);
    }
}
/**动态渲染修改标签位置 */
function setLabelPosition(angle:Number,labelText: any, event: any) {
    let pointLabel = new THREE.Vector3().lerpVectors(pointArrVector3[1], pointArrVector3[1], 0);
    pointLabel = WorldtoScreenPosition(pointLabel, event);
    labelText.style.left = pointLabel.x + 'px';
    labelText.style.top = pointLabel.y + 5 + 'px';
    labelText.innerHTML = angle.toFixed(2) +'°';
    /** 坐标转换，再把vector3坐标转为屏幕坐标*/
    function WorldtoScreenPosition(pos: any, eve: any) {
        const standardVector = pos.project(window.camera);// 进行投影转换，不太懂为啥转，里面执行了啥操作
        const widthHalf = eve.view.innerWidth / 2;
        const heightHalf = eve.view.innerHeight / 2;
        return {
            x: Math.round(standardVector.x * widthHalf + widthHalf),
            y: Math.round(-standardVector.y * heightHalf + heightHalf),
            z: 1
        }
    }
}